package com.alcohol.auth.server.service.impl;

import com.alcohol.auth.server.entity.SysOAuthClient;
import com.alcohol.auth.server.mapper.SysOAuthClientMapper;
import com.alcohol.auth.server.service.SysOAuthClientService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationException;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Map;
import java.util.Objects;

/**
 * 客户端认证信息Service——实现
 * @author LiXinYu
 * @date 2025/11/7
 */
@Service
public class SysOAuthClientServiceImpl implements SysOAuthClientService {

    @Resource
    private SysOAuthClientMapper sysOAuthClientMapper;

    /**
     * 保存注册的客户端
     * @param registeredClient 要保存的注册客户端
     */
    @Override
    public void save(RegisteredClient registeredClient) {

    }

    /**
     * 根据ID查询已注册的客户端
     * @param id 注册标识符
     * @return 已注册的客户端
     */
    @Override
    public RegisteredClient findById(String id) {
        throw new UnsupportedOperationException();
    }

    /**
     * 根据clientId查询已注册的客户端
     * @param clientId 客户端ID
     * @return 已注册的客户端
     */
    @Override
    public RegisteredClient findByClientId(String clientId) {
        LambdaQueryWrapper<SysOAuthClient> query = new LambdaQueryWrapper<>();
        query.eq(SysOAuthClient::getClientId, clientId);
        SysOAuthClient sysOAuthClient = sysOAuthClientMapper.selectOne(query);
        if (Objects.isNull(sysOAuthClient)) {
            throw new OAuth2AuthorizationCodeRequestAuthenticationException(new OAuth2Error("客户端查询异常，请检查数据库链接"), null);
        }

        RegisteredClient.Builder builder = RegisteredClient.withId(sysOAuthClient.getClientId())
                .clientId(sysOAuthClient.getClientId())
                .clientSecret("{noop}" + sysOAuthClient.getClientSecret())
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);

        // 授权类型
        for (String authorizedGrantType : sysOAuthClient.getAuthorizedGrantTypes()) {
            builder.authorizationGrantType(new AuthorizationGrantType(authorizedGrantType));
        }

        // 回调地址
        for (String redirectUri : sysOAuthClient.getRedirectUris()) {
            builder.redirectUri(redirectUri);
        }

        // scope
        for (String scope : sysOAuthClient.getScope()) {
            builder.scope(scope);
        }

        return builder
                .tokenSettings(TokenSettings.builder()
                        .accessTokenFormat(OAuth2TokenFormat.REFERENCE)
                        .accessTokenTimeToLive(Duration.ofSeconds(sysOAuthClient.getAccessTokenValidity()))
                        .refreshTokenTimeToLive(Duration.ofSeconds(sysOAuthClient.getRefreshTokenValidity()))
                        .build())
                .clientSettings(ClientSettings.builder()
//                        .requireAuthorizationConsent(false)
                        .requireAuthorizationConsent(true)
                        .build())
                .build();
    }

    /**
     * 获取客户端附加信息
     * @param clientId 客户端ID
     * @return 附加信息
     */
    @Override
    public Map<String, Object> getClientAdditionalParameters(String clientId) {
        LambdaQueryWrapper<SysOAuthClient> query = new LambdaQueryWrapper<>();
        query.eq(SysOAuthClient::getClientId, clientId);
        SysOAuthClient sysOAuthClient = sysOAuthClientMapper.selectOne(query);
        return sysOAuthClient.getAdditionalInformation();
    }

    @Override
    public SysOAuthClient getSysOAuthClient(String clientId) {
        LambdaQueryWrapper<SysOAuthClient> query = new LambdaQueryWrapper<>();
        query.eq(SysOAuthClient::getClientId, clientId);
        return sysOAuthClientMapper.selectOne(query);
    }
}
